package com.gvfish.dao;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.Transaction;

import net.sf.dozer.util.mapping.DozerBeanMapper;

import org.springframework.stereotype.Repository;

import com.gvfish.core.DozerBeanMapperFactory;
import com.gvfish.core.Page;
import com.gvfish.core.ReflectUtil;

/**
 * 公用的Dao。
 * 
 * @author ydy
 * 
 * @param <T>
 *            实体类型
 * @param <K>
 *            实体中id的种类。gae环境这里用key或者Long
 */
@Repository
public abstract class CommonDao<T, K>  {

	public abstract PersistenceManager getPersistenceManager() ;
	public abstract Class<T> getTClass();


	/**
	 * 利用反射更新实体，其中entity中null的属性不被更新
	 * 
	 * @param kind
	 * @param entity
	 * @param key
	 */
	public T update(T entity, K key) {
		PersistenceManager pm = getPersistenceManager();
		try {
			T old = pm.getObjectById(getTClass(), key);
			try {
				DozerBeanMapper dm = DozerBeanMapperFactory.getMapper();
				System.out.println(entity);
				System.out.println(old);
				dm.map(entity, old);
				System.out.println(old);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return old;
		} finally {
			pm.close();
		}
	}

	/**
	 * 保存一个实体
	 * 
	 * @param entity
	 * @return
	 */
	public T save(T entity) {
		PersistenceManager pm = getPersistenceManager();
		Transaction tx=pm.currentTransaction();
		try{
			tx.begin();
			pm.makePersistent(entity);
			tx.commit();
		}catch(Exception e){
			tx.rollback();
		}finally{
			if(!pm.isClosed())
				pm.close();
		}
		return entity;
	}

	/**
	 * 保存多个实体
	 * 
	 * @param entities
	 */
	public Collection<T> saveAll(Collection<T> entities) {
		return getPersistenceManager().makePersistentAll(entities);
	}

	public void saveAll(T[] entities) {
		PersistenceManager pm = getPersistenceManager();
		try {
			pm.makePersistentAll(entities);
		} finally {
			pm.close();
		}
	}

	public void del(K k) {
		PersistenceManager pm = getPersistenceManager();
		try {
			T t = (T) pm.getObjectById(getTClass(), k);
			pm.deletePersistent(t);
		} finally {
			pm.close();
		}
	}

	/**
	 * 
	 * @param c
	 */
	public void deleteAll(Collection<T> c) {
		PersistenceManager pm = getPersistenceManager();
		try {
			pm.deletePersistentAll(c);
		} finally {
			pm.close();
		}
	}

	public void deleteAll(T[] t) {
		PersistenceManager pm = getPersistenceManager();
		try{
			pm.deletePersistentAll(t);
		}finally{
			pm.close();
		}
	}

	/**
	 * 查找所有的实体，gae限制为1000条
	 * 
	 * @param kind
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<T> findAll() {
		System.out.println("in find All"+getTClass());
		// PersistenceManager pm = getPersistenceManager();
		// String str = "select from " + kind.getName();
		// List<T> results = null;
		// try {
		// results = (List) pm.newQuery(str).execute();
		// System.out.println(results);
		// } finally {
		// pm.close();
		// }
		// return results;
		List<T> result=null;
		PersistenceManager pm = getPersistenceManager();
		try{
			Query query = pm.newQuery(getTClass());
			pm.setDetachAllOnCommit(true);
			List<T> src = (List<T>) query.execute();
			result=src.subList(0, src.size());
		}finally{
			if(!pm.isClosed())
				pm.close();
		}
		return result;
		
	}

	/**
	 * 根据实体属性查找，只能对基本数据类型(及其包装器)属性和Stirng属性起作用
	 * 
	 * @param kind
	 * @param propertyName
	 * @param value
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<T> getByProperty(String propertyName, String value) {
		PersistenceManager pm = getPersistenceManager();
		try {
			Query query = pm.newQuery(getTClass(), propertyName + "==" + value);
			List<T> result = (List<T>) query.execute();
			if (result != null)
				return new ArrayList<T>(result.subList(0, result.size()));
			else
				return null;
		} finally {
			pm.close();
		}
	}

	// @SuppressWarnings("unchecked")
	// protected List<T> getByProperty(Class<T> kind, Map<String, String>
	// proMap) {
	// PersistenceManager pm = getPersistenceManager();
	// Query query = pm.newQuery(kind);
	// for (String pro : proMap.keySet()) {
	// query.setFilter(pro + "==" + proMap.get(pro));
	// }
	// return (List<T>) query.execute();
	// }

	/**
	 * 
	 */
	public T getById(K k) {
		return getPersistenceManager().getObjectById(getTClass(), k);
	}

	public Page<T> getByPage(Page<T> page) {
		 PersistenceManager pm = getPersistenceManager();
		 try{
			Query query = pm.newQuery(getTClass());
			query.setRange(page.getFirst(),page.getNextPage());
		 }finally{
			 pm.close();
		 }
		return null;

	}

	@SuppressWarnings("unchecked")
	public List<T> getByJDQL(String jdql,Integer start,Integer end) {
		PersistenceManager pm = getPersistenceManager();
		List<T> result=Collections.emptyList();
		try {
			Query query = pm.newQuery(jdql);
			if(start!=null&&end!=null){
				query.setRange(start, end);
			}
			List<T> src = (List<T>) query.execute();
			result=src.subList(0, src.size());
		} finally {
			pm.close();
		}
		return result;
	}

}
